#ifndef __CONVERTER_H__
  #define __CONVERTER_H__

#include <algorithm>
#include <iterator>
#include <string>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <climits>

using namespace std;

//! A handy converter for many conversions

/*!
This class can help to convert different datatypes to each other. We do not use istringstream & ostringstream
here, because they may cause crash(es) under some C++ STL implementations. we use sprintf & sscanf instead.
*/

class converter {
private:
  static long long power_10(short i);

public:
  enum trim_operation { trim_left = 0, trim_right, trim_left_and_right };

  //! checks the input to make sure, that it is a number (can be / or not be a negative number | can be / or not be a double number) (may throw an exception)
  static void check_number(const string &input, bool can_be_negative, bool can_be_double);

  //! converts an integert to a c-style string. the buffer must be allocated by the caller and must be large enough to store the result
  static void to_char(int i, char *s);

  //! converts a long long integert to a c-style string. the buffer must be allocated by the caller and must be large enough to store the result
  static void to_char(long long i, char *s);

  //! converts a string to a c-style string. the buffer must be allocated by the caller and must be large enough to store the result
  static void to_char(const string &s1, char *s2);

  //! converts a string to a short integer (may throw an exception)
  static short to_short(const string &s);

  //! converts a string to an unsigned short integer (may throw an exception)
  static unsigned short to_unsigned_short(const string &s);

  //! converts a string to an integer (may throw an exception)
  static int to_int(const string &s);

  //! converts a string to an unsigned integer (may throw an exception)
  static unsigned int to_unsigned_int(const string &s);

  //! converts a string to a long long integer (may throw an exception)
  static long long to_long_long(const string &s);

  //! converts a string to an unsigned long long integer (may throw an exception)
  static unsigned long long to_unsigned_long_long(const string &s);

  //! converts a string to a double (may throw an exception)
  static double to_double(const string &s);

  //! converts a char to a string
  static string &to_string(char c, string &output);

  //! converts an inteher to a string
  static string &to_string(int i, string &output);

  //! converts an unsigned inteher to a string
  static string &to_string(unsigned int i, string &output);

  //! converts a long long inteher to a string
  static string &to_string(long long i, string &output);

  //! converts an unsgined long long inteher to a string
  static string &to_string(unsigned long long i, string &output);

  //! converts a double to a string
  /*!
  after_comma's range is [0, 15]
  */
  static string &to_string(double d, string &output, unsigned short after_comma = 12);

  //! converts a string to a string. only useful for templates
  static string &to_string(const string &s, string &output);

  //! rounds i at the position j
  static long long round_long(long long i, short j);

  //! rounds d at the position j after comma
  static double round_double(double d, short j);

  //! converts the input to its uppercase format
  static string &to_upper(const string &s, string &output);

  //! converts the input to its lowercase format
  static string &to_lower(const string &s, string &output);

  //! converts the input to its thousand-separated format
  static string &thousand_separator(const string &s, string &output);

  //! removes all c characters in s
  static string &remove_all(const string &s, char c, string &output);

  //! replaces all c1 characters in s with c2
  static string &replace_all(const string &s, char c1, char c2, string &output);

  //! replaces all s1 strings in s with s2
  static string &replace_all(const string &s, const string &s1, const string &s2, string &output);

  //! trims the input (from left or right or both, trim characters can also be defined)
  static void trim(string &s, const string &trim_characters = " \r\n\t", trim_operation to = trim_left_and_right);

  //! converts a UCS2 c-style string to its UTF8 representation
  static string &to_utf8(const wchar_t *ws, string &output);

  //! converts a UCS2 string to its UTF8 representation
  static string &to_utf8(const wstring &ws, string &output);

  //! converts a UTF8 c-style string to its UCS2 representation
  static wstring &to_ucs2(const char *s, wstring &output);

  //! converts a UTF8 string to its UCS2 representation
  static wstring &to_ucs2(const string &s, wstring &output);
}; // class converter

#endif
